package com.example.verification.plugins.shiro;

import com.example.verification.model.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.session.mgt.WebSessionKey;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 自定义在线判断检测
 *
 * @author rcl
 * @date 2019/7/30 8:11
 */
public class OnlineSessionFilter extends AccessControlFilter {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;//注入redis缓存

    /**
     * 强制退出后重定向的地址
     */
//    @Value("${shiro.user.url}")
//    private String url;


    /**
     * 表示是否允许访问；mappedValue就是[urls]配置中拦截器参数部分，如果允许访问返回true，否则false；
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
            throws Exception {
        Subject subject = getSubject(request, response);
        HttpServletRequest re = (HttpServletRequest) request;

        String url = re.getServletPath();
        if (url.indexOf("/toLogin") != -1 || url.indexOf("/login") != -1 || url.indexOf("/static") != -1) {
            return true;
        }

        if (subject == null || subject.getSession() == null) {
            return true;
        }
        boolean status = false;

        SessionKey key = new WebSessionKey(subject.getSession().getId(), request, response);
        try {
            Session se = SecurityUtils.getSecurityManager().getSession(key);
            Object obj = se.getAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY);
            //获取当前登录用户的方式
            User user = (User) SecurityUtils.getSubject().getPrincipal();//方式1
//            User user1 = getUserInfo((String) subject.getSession().getId(), (HttpServletRequest) request, (HttpServletResponse) response);//方式二
            if (obj != null) {
                status = (Boolean) obj;
//                redisTemplate.opsForValue().set("user", user, 30, TimeUnit.SECONDS);//将用户信息存入到redis,并设置过期时间为30s/
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return status;
    }

    /**
     * 表示当访问拒绝时是否已经处理了；如果返回true表示需要继续处理；如果返回false表示该拦截器实例已经处理了，将直接返回即可。
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String type = httpServletRequest.getHeader("x-requested-with");
        if (type == null || type.trim().equals("")) {
            //用于重定向
            Subject subject = getSubject(request, response);
            if (subject != null) {
                subject.logout();
            }
            saveRequestAndRedirectToLogin(request, response);
        }else {
            //用于ajax请求，直接返回状态及提示
            HttpServletRequest re = (HttpServletRequest) request;
            HttpServletResponse rs = (HttpServletResponse) response;
            String url = re.getServletPath();

            rs.setContentType("application/json");
            rs.setCharacterEncoding("utf-8");
            rs.setStatus(200);
            rs.getWriter().print("{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
            //设置跨域（拦截器中）
            rs.setHeader("Access-Control-Allow-Origin", "*");
            rs.setHeader("Cache-Control", "no-cache");
        }
        return false;
    }

    // 跳转到登录页
//    @Override
//    protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
//        WebUtils.issueRedirect(request, response, url);
//    }

    /**
     * 获取当前登录用户的信息。根据sessionID进行获取
     *
     * @param [sessionID, request, response]
     * @return com.example.verification.model.User
     * @author rcl
     * @date 2019/7/30 9:25
     */
    public User getUserInfo(String sessionID, HttpServletRequest request, HttpServletResponse response) {
        boolean status = false;
        SessionKey key = new WebSessionKey(sessionID, request, response);
        try {
            Session se = SecurityUtils.getSecurityManager().getSession(key);
            Object obj = se.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
            //org.apache.shiro.subject.SimplePrincipalCollection cannot be cast to com.hncxhd.bywl.entity.manual.UserInfo
            SimplePrincipalCollection coll = (SimplePrincipalCollection) obj;
            return (User) coll.getPrimaryPrincipal();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}